{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "init success!\n"
     ]
    }
   ],
   "source": [
    "import sys,os \n",
    "root_path = os.path.abspath('../')\n",
    "sys.path.append(root_path)\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "import math\n",
    "from empyrical import alpha_beta, sharpe_ratio, max_drawdown, annual_return, tail_ratio\n",
    "from util.hw_util import *\n",
    "import warnings\n",
    "from pathos.pp import ParallelPool\n",
    "import pathos\n",
    "import math\n",
    "warnings.filterwarnings(\"ignore\")\n",
    "hu = HwUtil()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 选股方法\n",
    "# select_date 选股的日期\n",
    "# hu 数据存储类\n",
    "# for_day 需要从选股日期往前多少个交易日的数据\n",
    "#\n",
    "#\n",
    "# 当这个交易和这个code符合因子选股条件 \n",
    "# 就执行添加到select_sec_data这个dataframe\n",
    "# select_sec_data.loc[select_sec_data.shape[0]] = {'code':key,'pre_close':sec_data_0_md.close,'sort':compare_df_sum}\n",
    "# 最后返回\n",
    "def select_sec_list(select_date:date,hu:HwUtil,for_day:int):\n",
    "    #创建返回datafrmae\n",
    "    colums = ['code','pre_close','sort']\n",
    "    select_sec_data = pd.DataFrame(columns=colums)\n",
    "    select_date_str = select_date.strftime('%Y-%m-%d')\n",
    "    #获得往前N天的交易日和前一个交易日 并筛选出未复权的日K数据\n",
    "    sta_date_que = hu.get_previous_num_trade_date(hu.md_trade_date,select_date,for_day)\n",
    "    end_date_que = hu.get_previous_trade_date(hu.md_trade_date,select_date)\n",
    "    select_md_data = hu.trade_date_list_md[(hu.trade_date_list_md.date>=sta_date_que)&(hu.trade_date_list_md.date<=end_date_que)]\n",
    "    trade_mtss_day = hu.trade_mtss_day[(hu.trade_mtss_day.date>=sta_date_que)&(hu.trade_mtss_day.date<=end_date_que)]\n",
    "    #分组\n",
    "    groupby_code = select_md_data.groupby(\"code\")\n",
    "    # print(select_date_str)\n",
    "    for key in groupby_code.groups:\n",
    "        #从股票数据中查询今天是否交易\n",
    "        trade_date_list_info_c_key = hu.trade_date_list_info[(hu.trade_date_list_info['code']==key)&(hu.trade_date_list_info['add_date']==select_date)]\n",
    "        if len(trade_date_list_info_c_key)<=0:\n",
    "            continue\n",
    "        select_sec_md_data = groupby_code.get_group(key)\n",
    "        select_sec_md_data = select_sec_md_data.sort_values('date')\n",
    "        if len(select_sec_md_data)==0:\n",
    "            continue\n",
    "        if len(select_sec_md_data)<for_day:\n",
    "            continue\n",
    "        select_sec_md_data = select_sec_md_data.reset_index(drop=True)\n",
    "        select_sec_md_data['i'] = select_sec_md_data.index\n",
    "        sec_data_0_md = select_sec_md_data.iloc[-1]\n",
    "        sec_data_3_md = select_sec_md_data.iloc[0]\n",
    "        trade_mtss_day_sec = trade_mtss_day[trade_mtss_day.sec_code==key]\n",
    "        if len(trade_mtss_day_sec)==len(select_sec_md_data):\n",
    "            select_sec_md_data = select_sec_md_data.set_index(\"date\")\n",
    "            select_sec_md_data['day'] = select_sec_md_data.index\n",
    "            trade_mtss_day_sec = trade_mtss_day_sec.set_index(\"date\")\n",
    "            compare_df = pd.concat([select_sec_md_data, trade_mtss_day_sec], axis=1)\n",
    "            compare_df['diff_fin'] = compare_df['fin_value'].diff()\n",
    "            if len(compare_df[compare_df['diff_fin']>0])==(len(select_sec_md_data)-1):\n",
    "                if compare_df[compare_df['volume'].max()==compare_df['volume']].iloc[0].day==sec_data_0_md.date:\n",
    "                    compare_df_sum = compare_df['diff_fin'].sum()\n",
    "                    select_sec_data.loc[select_sec_data.shape[0]] = {'code':key,'pre_close':sec_data_0_md.close,'sort':compare_df_sum}\n",
    "\n",
    "        #北向资金抄底\n",
    "        # sec_data_0_md = select_sec_md_data.iloc[-1]\n",
    "        # sec_data_3_md = select_sec_md_data.iloc[0]\n",
    "        # trade_stk_hold_key_data = hu.trade_stk_hold[hu.trade_stk_hold.code==key]\n",
    "        # if len(trade_stk_hold_key_data)>0:\n",
    "        #     trade_stk_hold_key_data = trade_stk_hold_key_data[(trade_stk_hold_key_data.day<=sec_data_0_md.date)&(trade_stk_hold_key_data.day>=sec_data_3_md.date)]\n",
    "        #     if len(trade_stk_hold_key_data)==3:\n",
    "        #         select_sec_md_data['day'] = select_sec_md_data['date']\n",
    "        #         select_sec_md_data = select_sec_md_data.set_index('day')\n",
    "        #         trade_stk_hold_key_data = trade_stk_hold_key_data.set_index('day')\n",
    "        #         compare_df = pd.concat([trade_stk_hold_key_data, select_sec_md_data], axis=1)\n",
    "        #         if  (len(compare_df[compare_df['share_ratio']>0]))==3:\n",
    "        #             if (sec_data_0_md.close*1.05)<=sec_data_3_md.close:\n",
    "        #                 compare_df_sum = compare_df['share_ratio'].sum()\n",
    "        #                 select_sec_data.loc[select_sec_data.shape[0]] = {'code':key,'pre_close':sec_data_0_md.close,'sort':compare_df_sum}\n",
    "\n",
    "        # sec_data_0_md = select_sec_md_data.iloc[-1]\n",
    "        # sec_data_3_md = select_sec_md_data.iloc[0]\n",
    "        # trade_mtss_day_sec = trade_mtss_day[trade_mtss_day.sec_code==key]\n",
    "        # if len(trade_mtss_day_sec)==len(select_sec_md_data):\n",
    "        #     select_sec_md_data = select_sec_md_data.set_index(\"date\")\n",
    "        #     select_sec_md_data['day'] = select_sec_md_data.index\n",
    "        #     trade_mtss_day_sec = trade_mtss_day_sec.set_index(\"date\")\n",
    "        #     compare_df = pd.concat([select_sec_md_data, trade_mtss_day_sec], axis=1)\n",
    "        #     compare_df['diff_fin'] = compare_df['fin_value'].diff()\n",
    "        #     # print(compare_df[['code','fin_value','diff_fin']])\n",
    "        #     if len(compare_df[compare_df['diff_fin']>0])==(len(select_sec_md_data)-1):\n",
    "        #         if compare_df[compare_df['volume'].max()==compare_df['volume']].iloc[0].day==sec_data_0_md.date:\n",
    "        #             compare_df_sum = compare_df['diff_fin'].sum()\n",
    "        #             select_sec_data.loc[select_sec_data.shape[0]] = {'code':key,'pre_close':sec_data_0_md.close,'sort':compare_df_sum}\n",
    "        #\n",
    "        # 行情数据\n",
    "        # hu.trade_date_list_md\n",
    "        # 股票代码数据\n",
    "        # hu.trade_date_list_info\n",
    "        # 行情数据-除权除息后\n",
    "        # hu.trade_date_list_md_xd\n",
    "        # 交易日数据\n",
    "        # hu.md_trade_date\n",
    "        # 回测交易日数组\n",
    "        # hu.trade_date_list\n",
    "        # 北向资金交易日数据\n",
    "        # hu.md_trade_date_stk\n",
    "        # 北向资金持仓数据\n",
    "        # hu.trade_stk_hold\n",
    "        #写你的选股因子 当前交易日 和 股票 符合条件时添加 sort是排序的条件 不排序传0 \n",
    "        #select_sec_data.loc[select_sec_data.shape[0]] = {'code':key,'pre_close':sec_data_0_md.close,'sort':compare_df_sum}\n",
    "                                \n",
    "    return select_sec_data\n",
    "\n",
    "def pool_for(l_pool:int):\n",
    "    res_info_data_pool = pd.DataFrame(columns=['date','code'])\n",
    "    p_len = math.floor(len(hu.trade_date_list)/4)\n",
    "    if l_pool==1:\n",
    "        one_trade_date_list = hu.trade_date_list[0:p_len]\n",
    "    if l_pool==2:\n",
    "        one_trade_date_list = hu.trade_date_list[p_len:(p_len*2)]\n",
    "    if l_pool==3:\n",
    "        one_trade_date_list = hu.trade_date_list[(p_len*2):(p_len*3)]\n",
    "    if l_pool==4:\n",
    "        one_trade_date_list = hu.trade_date_list[(p_len*3):len(hu.trade_date_list)-1]\n",
    "    for td in one_trade_date_list:\n",
    "        th_day = td.strftime('%Y-%m-%d')\n",
    "        print(th_day)\n",
    "        select_sec_data = select_sec_list(td,hu,hu.for_day)\n",
    "        # print(len(select_sec_data))\n",
    "        if len(select_sec_data)==0:\n",
    "            continue\n",
    "        if hu.size_sec!=0:\n",
    "            if len(select_sec_data)>hu.size_sec:\n",
    "                select_sec_data.sort_values(\"sort\",inplace=True,ascending=False)\n",
    "                select_sec_data = select_sec_data[0:hu.size_sec]\n",
    "        res_info_data_pool.loc[res_info_data_pool.shape[0]] = {'date':th_day,'code':select_sec_data['code'].tolist()}\n",
    "    return res_info_data_pool\n",
    "\n",
    "#循环选股\n",
    "def start_test(hu:HwUtil,size_sec:int,for_day:int):\n",
    "    del hu.res_info_data\n",
    "    hu.res_info_data = pd.DataFrame(columns=['date','code'])\n",
    "    hu.for_day = for_day\n",
    "    hu.size_sec = size_sec\n",
    "    pool = pathos.multiprocessing.Pool() \n",
    "    result = pool.map_async(pool_for,[1,2,3,4]).get()\n",
    "    hu.res_info_data = pd.concat((hu.res_info_data,result[0],result[1],result[2],result[3]))\n",
    "    pool.close()\n",
    "    pool.join()\n",
    "    \n",
    "\n",
    "\n",
    "\n",
    "#收益统计筛选\n",
    "def sec_filter(hu:HwUtil,pre_md_data:DataFrame,to_day_md_data:DataFrame):\n",
    "    md = to_day_md_data.iloc[0]\n",
    "    pre = pre_md_data.iloc[-1]\n",
    "    ppre = pre_md_data.iloc[-2]\n",
    "    if md.close>pre.close*1.09:\n",
    "        return False\n",
    "    else:\n",
    "        if md.close<pre.close*0.91:\n",
    "            return False\n",
    "        else:\n",
    "            if pre.close<ppre.close*0.91:\n",
    "                return False\n",
    "            else:\n",
    "                return True\n",
    "\n",
    "#num_sell_day:几天后卖出\n",
    "#test_money:测试今天\n",
    "#day_num:几天后卖出\n",
    "#sell_par:卖出入字段 open close\n",
    "#buy_par:买入字段 open close\n",
    "#hold_money_r:持仓占比 0.5 or 1.0\n",
    "def start_test_profit(hu:HwUtil,num_sell_day:int,test_money:float,day_num:int,sell_par:str,buy_par:str,hold_money_r:float):\n",
    "    print(\"开始收益统计\")\n",
    "    del hu.ret_data\n",
    "    buy_fee = 0.0002\n",
    "    sell_fee = 0.0012\n",
    "    hu.ret_data = pd.DataFrame(columns=['date','code','buy','sell','return','sum_return','buy_fee','sell_fee'])\n",
    "    g_money = test_money\n",
    "    for index, row in hu.res_info_data.iterrows():\n",
    "        date = datetime.strptime(row['date'], \"%Y-%m-%d\").date()\n",
    "        print(date)\n",
    "        code_list = row['code']\n",
    "        p_sec_num_buy = pd.DataFrame(columns=['code','buy_money','sell_money'])\n",
    "        for s_code in code_list:\n",
    "            to_day_md_data = hu.trade_date_list_md_xd[(hu.trade_date_list_md_xd['date']==date)&(hu.trade_date_list_md_xd['code']==s_code)]\n",
    "            next_md_data = hu.trade_date_list_md_xd[(hu.trade_date_list_md_xd['date']>date)&(hu.trade_date_list_md_xd['code']==s_code)]\n",
    "            pre_md_data = hu.trade_date_list_md_xd[(hu.trade_date_list_md_xd['date']<date)&(hu.trade_date_list_md_xd['code']==s_code)]\n",
    "            if len(pre_md_data)>day_num:\n",
    "                md_num_data = pre_md_data.iloc[0-day_num]\n",
    "            else:\n",
    "                md_num_data = pre_md_data.iloc[0]\n",
    "            sell_money = 0\n",
    "            buy_money = 0\n",
    "            if len(next_md_data)>(num_sell_day-1):\n",
    "                next_md_data = next_md_data[num_sell_day-1:num_sell_day]\n",
    "                next_md = next_md_data.iloc[0]\n",
    "                sell_money = next_md[sell_par]\n",
    "            if len(to_day_md_data)>0:\n",
    "                md = to_day_md_data.iloc[0]\n",
    "                buy_money = md[buy_par]\n",
    "                pre = pre_md_data.iloc[-1]\n",
    "                ppre = pre_md_data.iloc[-2]\n",
    "                is_sec_filter = sec_filter(hu,pre_md_data,to_day_md_data)\n",
    "                if is_sec_filter==True:\n",
    "                    p_sec_num_buy.loc[p_sec_num_buy.shape[0]] = {'code':md.code,'sell_money':sell_money,'buy_money':buy_money}\n",
    "            to_day_md_data = None\n",
    "            next_md_data = None\n",
    "            sell_money = 0\n",
    "            buy_money = 0\n",
    "        if len(p_sec_num_buy)==0:\n",
    "            hu.ret_data.loc[hu.ret_data.shape[0]] = {'date':date,'code':code_list,'buy':0,'sell':0,'return':0,\"sum_return\":g_money,'buy_fee':0,'sell_fee':0}\n",
    "        else:\n",
    "            p_sec_num_buy['money'] = (g_money*hold_money_r)/len(p_sec_num_buy)\n",
    "            p_sec_num_buy['vol'] = p_sec_num_buy['money']/(p_sec_num_buy['buy_money']*100)\n",
    "            p_sec_num_buy['vol'] = round(p_sec_num_buy['vol'],0)*100\n",
    "            p_sec_num_buy['b_money'] = p_sec_num_buy['buy_money']*p_sec_num_buy['vol']\n",
    "            p_sec_num_buy['s_money'] = p_sec_num_buy['sell_money']*p_sec_num_buy['vol']\n",
    "            buy_money = p_sec_num_buy['b_money'].sum()\n",
    "            sell_money = p_sec_num_buy['s_money'].sum()\n",
    "            buy_money_fee = buy_money*buy_fee\n",
    "            sell_money_fee = sell_money*sell_fee\n",
    "            if buy_money == 0 or sell_money==0:\n",
    "                hu.ret_data.loc[hu.ret_data.shape[0]] = {'date':date,'code':code_list,'buy':0,'sell':0,'return':0,\"sum_return\":g_money,'buy_fee':0,'sell_fee':0}\n",
    "            else:\n",
    "                return_money = sell_money-buy_money-buy_money_fee-sell_money_fee\n",
    "                g_money = g_money+return_money\n",
    "                hu.ret_data.loc[hu.ret_data.shape[0]] = {'date':date,'code':code_list,'buy':buy_money,'sell':sell_money,'return':return_money,\"sum_return\":g_money,'buy_fee':buy_money_fee,'sell_fee':sell_money_fee}\n",
    "            p_sec_num_buy = None\n",
    "            buy_money = 0\n",
    "            sell_money = 0\n",
    "            return_money = 0\n",
    "    print(\"收益统计完成\")\n",
    "    p_profit(hu,test_money)\n",
    "\n",
    "    \n",
    "def p_profit(hu:HwUtil,test_money:float):\n",
    "    z_money = test_money\n",
    "    huret_data = hu.ret_data.set_index('date')\n",
    "    hu.ret_data[['date', 'sum_return']].plot(figsize=(16,9), secondary_y='sum_return')\n",
    "    hu.ret_data['returns_a'] = hu.ret_data['return']/hu.ret_data['sum_return']\n",
    "    sum_money = hu.ret_data.iloc[-1].sum_return\n",
    "    win = sum_money-z_money\n",
    "    max_draw = max_drawdown(hu.ret_data['returns_a'].values)*100\n",
    "    ret_r = win/test_money*100\n",
    "    year_win_r = win/z_money/len(hu.ret_data)*365*100\n",
    "    win_r = len(hu.ret_data[hu.ret_data['return']>0])/len(hu.ret_data)*100\n",
    "    max_money_use_r = hu.ret_data['buy'].max()/hu.ret_data[hu.ret_data['buy'].max()==hu.ret_data['buy']].iloc[0].sum_return*100\n",
    "    l_max_los = hu.ret_data['return'].min()\n",
    "    l_max_los_r = hu.ret_data['returns_a'].min()*100\n",
    "    l_max_win = hu.ret_data['return'].max()\n",
    "    l_max_win_r = hu.ret_data['returns_a'].max()*100\n",
    "    buy_fee_money = hu.ret_data['buy_fee'].sum()\n",
    "    sell_fee_money = hu.ret_data['sell_fee'].sum()\n",
    "    print(\"总资金:\"+str(round(sum_money,2))+\"\")\n",
    "    print(\"总收益:\"+str(round(win,2))+\"\")\n",
    "    print(\"收益率:\"+str(round(ret_r,2))+\"%\")\n",
    "    print(\"年化收益率:\"+str(round(year_win_r,2))+\"%\")\n",
    "    print(\"最大回撤:\"+str(round(max_draw,2))+\"%\")\n",
    "    print(\"胜率:\"+str(round(win_r,2))+\"%\")\n",
    "    print(\"最大资金使用率:\"+str(round(max_money_use_r,2))+\"%\")\n",
    "    print(\"当次最大亏损:\"+str(round(l_max_los,2))+\"\")\n",
    "    print(\"当次最大亏损率:\"+str(round(l_max_los_r,2))+\"%\")\n",
    "    print(\"当次最大盈利:\"+str(round(l_max_win,2))+\"\")\n",
    "    print(\"当次最大盈利率:\"+str(round(l_max_win_r,2))+\"%\")\n",
    "    print(\"总手续费:\"+str(round(sell_fee_money+buy_fee_money,2))+\"\")\n",
    "    print(\"买入手续费:\"+str(round(buy_fee_money,2))+\"\")\n",
    "    print(\"卖出手续费:\"+str(round(sell_fee_money,2))+\"\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "查询除权除息\n",
      "select distinct * from sec_data.sec_xr_xd where 1=1 and a_xr_date >='2021-07-12' and a_xr_date<'2021-07-23'\n",
      "查询除权除息-完成\n",
      "查询行情\n",
      "查询行情-完成\n",
      "开始除权除息\n",
      "除权除息-完成\n",
      "开始交易日\n",
      "开始交易日-完成\n",
      "获取北向资金交易日\n",
      "select distinct * from sec_data.sec_stk_day where 1=1 and day >='2021-07-12' and day<'2021-07-23'\n",
      "获取北向资金交易日-完成\n",
      "获取北向资金持仓\n",
      "select distinct * from sec_data.sec_stk_hold where 1=1 and day >='2021-07-12' and day<'2021-07-23'\n",
      "获取北向资金持仓-完成\n",
      "获取融资融卷数据\n",
      "select distinct * from sec_data.sec_mtss_day where 1=1 and date >='2021-07-12' and date<'2021-07-23'\n",
      "获取融资融卷数据-完成\n"
     ]
    }
   ],
   "source": [
    "#初始化数据\n",
    "#sta_date_str 回测开始时间\n",
    "#end_date_str 回测结束时间\n",
    "#for_day      需要选股当天往前多少个交易日的数据\n",
    "#is_ck        是否使用ck数据库\n",
    "#is_stk       是否初始化北向资金\n",
    "# 此方法仅初始化一次 无需重复执行\n",
    "#\n",
    "# 行情数据\n",
    "# hu.trade_date_list_md\n",
    "# 股票代码数据\n",
    "# hu.trade_date_list_info\n",
    "# 行情数据-除权除息后\n",
    "# hu.trade_date_list_md_xd\n",
    "# 交易日数据\n",
    "# hu.md_trade_date\n",
    "# 回测交易日数组\n",
    "# hu.trade_date_list\n",
    "# 北向资金交易日数据\n",
    "# hu.md_trade_date_stk\n",
    "# 北向资金持仓数据\n",
    "# hu.trade_stk_hold\n",
    "# 选股结果\n",
    "# hu.res_info_data\n",
    "# 计算收益结果\n",
    "# hu.ret_data\n",
    "# 任何地方均可以调用\n",
    "hu.init_md_trade_sec_data(sta_date_str='2021-07-15',end_date_str='2021-07-23',for_day=3,is_ck=True,is_stk=True,is_mtss=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2021-07-152021-07-192021-07-162021-07-20\n",
      "\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "#开始回测\n",
    "#hu           数据类\n",
    "#size_sec     每天选多少支股票 选股方法的sort有值会根据sort排序 传0则全部\n",
    "#for_day      需要选股当天往前多少个交易日的数据\n",
    "start_test(hu=hu,size_sec=3,for_day=3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>date</th>\n",
       "      <th>code</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2021-07-15</td>\n",
       "      <td>[603786.XSHG, 603489.XSHG, 002572.XSHE]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2021-07-16</td>\n",
       "      <td>[603786.XSHG, 603489.XSHG, 002572.XSHE]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2021-07-19</td>\n",
       "      <td>[603786.XSHG, 603489.XSHG, 002572.XSHE]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2021-07-20</td>\n",
       "      <td>[603786.XSHG, 603489.XSHG, 002572.XSHE]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2021-07-21</td>\n",
       "      <td>[603786.XSHG, 603489.XSHG, 002572.XSHE]</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "         date                                     code\n",
       "0  2021-07-15  [603786.XSHG, 603489.XSHG, 002572.XSHE]\n",
       "0  2021-07-16  [603786.XSHG, 603489.XSHG, 002572.XSHE]\n",
       "0  2021-07-19  [603786.XSHG, 603489.XSHG, 002572.XSHE]\n",
       "0  2021-07-20  [603786.XSHG, 603489.XSHG, 002572.XSHE]\n",
       "1  2021-07-21  [603786.XSHG, 603489.XSHG, 002572.XSHE]"
      ]
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "hu.res_info_data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [],
   "source": [
    "hu.res_info_data.to_parquet(\"data/stk_hold_test.parquet\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {},
   "outputs": [],
   "source": [
    "hu.res_info_data = pd.read_parquet(\"data/stk_hold_test.parquet\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {},
   "outputs": [],
   "source": [
    "hu.res_info_data = hu.res_info_data[42:-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {},
   "outputs": [],
   "source": [
    "new_res_info_data = hu.res_info_data\n",
    "for index, row in new_res_info_data.iterrows():\n",
    "    code_list = row['code']\n",
    "    code_list = code_list[0:1]\n",
    "    row['code'] = code_list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "开始收益统计\n",
      "2021-07-22\n",
      "收益统计完成\n"
     ]
    },
    {
     "ename": "TypeError",
     "evalue": "ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-12-3c1654a91ac9>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      7\u001b[0m \u001b[0;31m#hold_money_r   持仓占比 0.5 or 1.0\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      8\u001b[0m \u001b[0;31m# start_test_profit(hu=hu,num_sell_day=3,test_money=1000000,day_num=1,sell_par='close',buy_par='close',hold_money_r=0.3)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 9\u001b[0;31m \u001b[0mstart_test_profit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mhu\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mhu\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mnum_sell_day\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mtest_money\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1000000\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mday_num\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0msell_par\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'close'\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mbuy_par\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'close'\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mhold_money_r\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0.5\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     10\u001b[0m \u001b[0;31m# start_test_profit(hu=hu,num_sell_day=1,test_money=1000000,day_num=1,sell_par='close',buy_par='close',hold_money_r=1)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     11\u001b[0m \u001b[0;31m# 3day sell-close buy-close 仓位:0.3 年化:44.3% 回撤:-13.42% 胜率:55.96%\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m<ipython-input-2-871cfe3506c7>\u001b[0m in \u001b[0;36mstart_test_profit\u001b[0;34m(hu, num_sell_day, test_money, day_num, sell_par, buy_par, hold_money_r)\u001b[0m\n\u001b[1;32m    182\u001b[0m             \u001b[0mreturn_money\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    183\u001b[0m     \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"收益统计完成\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 184\u001b[0;31m     \u001b[0mp_profit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mhu\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mtest_money\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    185\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    186\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m<ipython-input-2-871cfe3506c7>\u001b[0m in \u001b[0;36mp_profit\u001b[0;34m(hu, test_money)\u001b[0m\n\u001b[1;32m    192\u001b[0m     \u001b[0msum_money\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mhu\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mret_data\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0miloc\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msum_return\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    193\u001b[0m     \u001b[0mwin\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msum_money\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0mz_money\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 194\u001b[0;31m     \u001b[0mmax_draw\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmax_drawdown\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mhu\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mret_data\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'returns_a'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalues\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0;36m100\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    195\u001b[0m     \u001b[0mret_r\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mwin\u001b[0m\u001b[0;34m/\u001b[0m\u001b[0mtest_money\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0;36m100\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    196\u001b[0m     \u001b[0myear_win_r\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mwin\u001b[0m\u001b[0;34m/\u001b[0m\u001b[0mz_money\u001b[0m\u001b[0;34m/\u001b[0m\u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mhu\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mret_data\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0;36m365\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0;36m100\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/miniconda3/envs/tf2/lib/python3.8/site-packages/empyrical/stats.py\u001b[0m in \u001b[0;36mmax_drawdown\u001b[0;34m(returns, out)\u001b[0m\n\u001b[1;32m    390\u001b[0m     )\n\u001b[1;32m    391\u001b[0m     \u001b[0mcumulative\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mstart\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m100\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 392\u001b[0;31m     \u001b[0mcum_returns\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mreturns_array\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstarting_value\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mstart\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mout\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mcumulative\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    393\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    394\u001b[0m     \u001b[0mmax_return\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfmax\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0maccumulate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcumulative\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maxis\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/miniconda3/envs/tf2/lib/python3.8/site-packages/empyrical/stats.py\u001b[0m in \u001b[0;36mcum_returns\u001b[0;34m(returns, starting_value, out)\u001b[0m\n\u001b[1;32m    250\u001b[0m         \u001b[0;32mreturn\u001b[0m \u001b[0mreturns\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcopy\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    251\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 252\u001b[0;31m     \u001b[0mnanmask\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0misnan\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mreturns\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    253\u001b[0m     \u001b[0;32mif\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0many\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnanmask\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    254\u001b[0m         \u001b[0mreturns\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mreturns\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcopy\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mTypeError\u001b[0m: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''"
     ]
    }
   ],
   "source": [
    "#hu             数据类\n",
    "#num_sell_day   几天后卖出 1为明天卖出\n",
    "#test_money     回测金额\n",
    "#day_num        往前几天买入 默认1 勿修改\n",
    "#sell_par       卖出字段 open close\n",
    "#buy_par        买入字段 open close\n",
    "#hold_money_r   持仓占比 0.5 or 1.0\n",
    "# start_test_profit(hu=hu,num_sell_day=3,test_money=1000000,day_num=1,sell_par='close',buy_par='close',hold_money_r=0.3)\n",
    "start_test_profit(hu=hu,num_sell_day=2,test_money=1000000,day_num=1,sell_par='close',buy_par='close',hold_money_r=0.5)\n",
    "# start_test_profit(hu=hu,num_sell_day=1,test_money=1000000,day_num=1,sell_par='close',buy_par='close',hold_money_r=1)\n",
    "# 3day sell-close buy-close 仓位:0.3 年化:44.3% 回撤:-13.42% 胜率:55.96%\n",
    "# 2day sell-close buy-close 仓位:0.5 年化:57.21%   回撤:-16。26%    胜率:57.21%\n",
    "# 1day sell-close buy-close 仓位:1   年化:41.56%   回撤:-20.8%    胜率:53.21%\n",
    "#2调\n",
    "# 3day sell-close buy-close 仓位:0.3 年化:55.02%   回撤:-12.18%   胜率:56.88%\n",
    "# 2day sell-close buy-close 仓位:0.5 年化:75.02%   回撤:-14.31%   胜率:56.88%\n",
    "# 1day sell-close buy-close 仓位:1   年化:63.26%   回撤:-19.3%    胜率:55.05%\n",
    "#3调\n",
    "# 3day sell-close buy-close 仓位:0.3 年化:65.69%   回撤:-11.90%    胜率:56.88%\n",
    "# 2day sell-close buy-close 仓位:0.5 年化:86.58%   回撤:-14.31%    胜率:57.80%\n",
    "# 1day sell-close buy-close 仓位:1   年化:70.67%   回撤:-18.86%    胜率:54.13%"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "ss = hu.ret_data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "047edc17978fcec36365898495b1b6de8a14521ee4f737035e20a6ab22989f99"
  },
  "kernelspec": {
   "display_name": "Python 3.9.4 64-bit",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.4"
  },
  "metadata": {
   "interpreter": {
    "hash": "b9349baf60296d31c1fc16cfd4f7454d7a12625f03dcdcca8738bf86ef65e21c"
   }
  },
  "orig_nbformat": 2
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
